﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using InductBase;
using SharpBolt.Graphics;
using SharpBolt.Graphics.GraphicSources;
using SharpBolt.Graphics.Structs;
using SharpBolt.Graphics.GraphicInstances;
using SharpBolt;
using SharpBolt.Basics;
using SharpBolt.Animation;

namespace TestGame.Logic
{
    class PlayRoom
    {
        Vec2i MapSize;
        Vec2 CellSize;
        ImageSource PadChip, KeyChip, BallChip, JokerChip, GiftChip;

        GraphicInstance Pointer;

        List<Chip> Chips;
        Chip[,] Map;

        Chip GrabbedChip;

        public PlayRoom()
        {
            MapSize = new Vec2i(4, 5);
            CellSize = new Vec2(64, 64);
            Chips = new List<Chip>();
            Map = new Chip[MapSize.X, MapSize.Y];
        }

        Chip GetAt(Vec2i position)
        {
            return Map[position.X, position.Y];
        }

        void UpdateMap(){
            Array.Clear(Map, 0, Map.Length);

            foreach (var chip in Chips)
            {
                Map[chip.Position.X, chip.Position.Y] = chip;
            }
        }

        public void Init()
        {
            PadChip = ImageSource.LoadImage("tiles/pad.png");
            KeyChip = ImageSource.LoadImage("tiles/key.png");
            BallChip = ImageSource.LoadImage("tiles/ball.png");
            JokerChip = ImageSource.LoadImage("tiles/joker.png");
            GiftChip = ImageSource.LoadImage("tiles/gift.png");

            Pointer = new ImageInstance(ImageSource.LoadImage("tiles/joker.png"));

            GenerateChips();
        }

        void GenerateChips()
        {
            for (int i = 0; i < 10; i++)
            {
                Vec2i position = new Vec2i(
                    Global.Random.Next(0, MapSize.X-1),
                    Global.Random.Next(0, MapSize.Y-1)
                    );
                
                if(Chips.Any( p =>p.Position == position)){
                    i--;
                    continue;
                }
                
                Chip chip = new Chip();
                
                chip.Type = (Chip.ChipType)Global.Random.Next(1,5);


                if (chip.Type == Chip.ChipType.Gift)
                {
                    chip.Graphic = new ImageInstance(GiftChip);
                    chip.Highlight += new EventHandler(chip_Pop);  
                }
                else if (chip.Type == Chip.ChipType.Joker)
                {
                    chip.Graphic = new ImageInstance(JokerChip);
                    chip.Highlight += new EventHandler(chip_Pop);  
                }
                else if (chip.Type == Chip.ChipType.Key)
                {
                    chip.Graphic = new ImageInstance(KeyChip);
                    chip.Highlight += new EventHandler(chip_Pop);  
                }
                else
                {
                    chip.Type = Chip.ChipType.Ball;
                    chip.Graphic = new ImageInstance(BallChip);
                    chip.Highlight += new EventHandler(chip_Rise);
                    chip.UnHighlight += new EventHandler(chip_Drop);
                }


                chip.Position = position;
                chip.Transformation = Transformation.Default;

                chip.isMoved = true;

                Chips.Add(chip);
            }
        }

        void chip_Drop(object sender, EventArgs e)
        {
            AnimateDrop((Chip)sender);
        }

        void chip_Pop(object sender, EventArgs e)
        {
            AnimatePop((Chip)sender);
        }

        void chip_Rise(object sender, EventArgs e)
        {
            AnimateRise((Chip)sender);
        }

        void PlaceChips()
        {
            foreach (var chip in Chips)
            {
                chip.Transformation = new Transformation(
                    CellSize * chip.Position + CellSize / 2,
                    new Vec2(1, 1),
                    -CellSize/2,
                    0);

                if (chip.isMoved)
                {
                    chip.isMoved = false;

                    Global.AnimatorManager.OptionEasing = Easing.EaseOutElastic;
                    Global.AnimatorManager.Animate(
                        chip.Graphic,
                        new Animator.AnimationKey()
                        {
                            Transformation = chip.Graphic.Transformation.Copy().ScaleUp(new Vec2(1.5, 1.5)),
                            DColor = Colors.Aqua.ToDColor()
                        },
                        new Animator.AnimationKey()
                        {
                            Transformation = chip.Transformation.Copy(),
                            DColor = Colors.White.ToDColor()
                        },
                        200
                        );   
                }
            }
        }

        bManipulator pointer;
        Vec2i currentIndex;

        void GrabAndDrop()
        {
            if (Global.InputObserver.IsKeyPressed("grab"))
            {
                if (currentIndex.X < 0) return;

                GrabbedChip = Chips.Find(p => p.Position == currentIndex);
            }

            if (Global.InputObserver.IsKeyReleased("grab"))
            {
                if (currentIndex.X < 0) return;

                if (GrabbedChip != null)
                    if (GetAt(currentIndex) == null)
                {  
                    GrabbedChip.Position = currentIndex;
                    GrabbedChip.isMoved = true;
                    UpdateMap();
                }
            }

        }


        void PlacePointer()
        {
            pointer = Global.InputObserver.Pointer;

            if (pointer != null)
            {
                Pointer.Transformation.Position = pointer.InViewPosition() - CellSize / 2;
                currentIndex = GetIndex(pointer.InViewPosition());
            }
        }

        Vec2i GetIndex(Vec2 position)
        {
            for (int i = 0; i < MapSize.X; i++)
            {
                for (int j = 0; j < MapSize.Y; j++)
                {
                    Rec rec = Rec.FromLocationSize(new Vec2(i, j) * CellSize, CellSize);
                    if (rec.Contains(position)) return new Vec2i(i, j);
                }
            }

            return new Vec2i(-1, -1);
        }

        Chip UnderChip;

        void AnimateHighLightedCell()
        {
            Chip NewUnderChip = Chips.Find(p => p.Position == currentIndex);

            //UnHighlight old stone
            if (UnderChip != null &&
                (NewUnderChip == null || UnderChip.Position != currentIndex)
                )
            { 
               
                UnderChip.OnUnHighlight();                
            }

            //Highlight new stone
            if (NewUnderChip != null && UnderChip != NewUnderChip)
            {
                if (NewUnderChip != null)
                {
                    NewUnderChip.OnHighlight();

                    var snd = NewUnderChip.blink.GetInstance();
                    snd.Volume = .25;
                    snd.Play();
                }
            }

            UnderChip = NewUnderChip;

        }

        private static void AnimatePop(Chip chip)
        {
            if (!Global.AnimatorManager.IsCurrentlyAnimated(chip.Graphic))
            {
                Global.AnimatorManager.OptionGuaranteedEnded = true;
                Global.AnimatorManager.OptionEasing = Easing.PingPong(Easing.EaseLinear, Easing.EaseLinear);
                Global.AnimatorManager.AnimateTo(
                        chip.Graphic,
                        chip.Transformation.Copy().ScaleUp(new Vec2(1.25, 1.25)),
                        Colors.Aqua,
                        500);
            }
        }

        private static void AnimateRise(Chip chip)
        {
            Global.AnimatorManager.OptionGuaranteedEnded = false;
            Global.AnimatorManager.OptionImportance = -1;
            Global.AnimatorManager.AnimateTo(
                    chip.Graphic,
                    chip.Transformation.Copy().ScaleUp(new Vec2(1.25, 1.25)),
                    Colors.White,
                    100);
        }

        private void AnimateDrop(Chip chip)
        {
            Global.AnimatorManager.OptionGuaranteedEnded = false;
            Global.AnimatorManager.OptionImportance = -1;
            Global.AnimatorManager.OptionEasing = Easing.EaseOutBounce;
            Global.AnimatorManager.AnimateTo(
                    chip.Graphic,
                    chip.Transformation.Copy(),
                    Colors.White,
                    800);
        }

        void HighLightCell(Painter painter)
        {
            if (currentIndex.X < 0) return;

            PadChip.Draw(painter, currentIndex * CellSize, new Color(100, 0, 255, 255));
        }

        public void Update()
        {
            PlaceChips();
            PlacePointer();
            GrabAndDrop();
            AnimateHighLightedCell();
        }

        public void Draw(Painter painter)
        {
            for (int i = 0; i < MapSize.X; i++)
            {
                for (int j = 0; j < MapSize.Y; j++)
                {
                    PadChip.Draw(painter, new Vec2(i, j) * CellSize);
                }
            }

            for (int i = 0; i < MapSize.X; i++)
            {
                int j = MapSize.Y;
                PadChip.Draw(painter, new Vec2(i, j) * CellSize, Colors.Green);
            }

            HighLightCell(painter);

            foreach (var chip in Chips)
            {
                chip.Graphic.Draw(painter);
            }
            

            //Pointer.Draw(painter);
        }
    }
}
